package com.tanhua.server.service;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.commons.template.OssTemplate;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.server.interceptor.UserHolder;
import org.bson.types.ObjectId;

import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.VideoApi;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

@Service
public class VideoService {
    @Reference
    private VideoApi videoApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private FastFileStorageClient storageClient;
    @Autowired
    private FdfsWebServer fdfsWebServer;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 接口名称：小视频列表
     */
    @Cacheable(value = "videoList",key = "#p0 + '_' + #p1")
    public PageResult queryVideoList(Integer page, Integer pagesize) {
        //【推荐视频：首先从redis获取数据，如果没有获取到再去mongo中查询】
        //【先从redis中获取推荐数据】
        PageResult pageResult = findAllByRecommend(page,pagesize);
        if (pageResult == null) {
            //1. 分页查询小视频列表
            pageResult = videoApi.queryVideoList(page, pagesize);
        }
        //2. 获取分页数据
        List<Video> videoList = (List<Video>) pageResult.getItems();
        //3. 创建返回的vo集合
        List<VideoVo> voList = new ArrayList<>();
        //4. 封装vo集合
        if (videoList != null) {
            for (Video video : videoList) {
                //3.1 创建vo对象，封装前端返回的数据
                VideoVo vo = new VideoVo();
                BeanUtils.copyProperties(video,vo);
                //3.2 根据用户id查询用户并封装
                UserInfo userInfo = userInfoApi.findById(video.getUserId());
                if (userInfo!= null) {
                    BeanUtils.copyProperties(userInfo,vo);
                }
                //3.3 设置小视频封面
                vo.setCover(video.getPicUrl());
                //3.4 设置id、签名
                vo.setId(video.getId().toString());
                vo.setSignature(video.getText());
                vo.setHasLiked(0);
                // 设置是否关注用户：如果关注用户App会点亮图标
                String key = "followUser_" + UserHolder.getUserId() + "_" + video.getUserId();
                if (redisTemplate.hasKey(key)) {
                    vo.setHasFocus(1);
                }else {
                    vo.setHasFocus(0);
                }
                //3.5 vo添加到集合
                voList.add(vo);
            }
        }

        //5. 设置到分页对象中
        pageResult.setItems(voList);
        return pageResult;
    }

    private PageResult findAllByRecommend(Integer page, Integer pagesize) {
        //1. 构造key
        String key = "QUANZI_VIDEO_RECOMMEND_" + UserHolder.getUserId();
        //2. 获取redis中的推荐数据（vid）
        String values = redisTemplate.opsForValue().get(key);
        if(StringUtils.isEmpty(values)) {
            return null;
        }
        //3. 分割字符串
        String[] pids = values.split(",");
        int counts = pids.length;

        //4. 查询的开始行 (举例：每页显示3条)
        int startIndex = (page - 1) * pagesize;
        //5. 判断：查询的起始行小于总行数
        if(startIndex < pids.length) { //起始条数小于数据总数
            int endIndex = startIndex + pagesize - 1;
            if (endIndex >= pids.length) {
                endIndex = pids.length - 1;
            }
            //5. 遍历：获取pid集合
            List<Long> pidList = new ArrayList<>();
            for (int i = startIndex; i <= endIndex; i++) {
                pidList.add(Long.valueOf(pids[i]));
            }
            //6. 把pid集合作为条件查询
            List<Video> list = videoApi.findByVids(pidList);
            return new PageResult(page, pagesize, counts, list);
        }
        return null;
    }

    @Autowired
    private VideoMqService videoMqService;

    /**
     * 接口名称：视频上传
     */
    @CacheEvict(value = "videoList",allEntries = true)
    public ResponseEntity<Object> saveVideos(
            MultipartFile videoThumbnail,
            MultipartFile videoFile,
            String content) throws Exception {
        //1. 图片上传到阿里云
        String picUrl =
                ossTemplate.upload(videoThumbnail.getOriginalFilename(),
                        videoThumbnail.getInputStream());

        //2. 视频上传到fastdfs
        // 获取文件后缀
        String fileName = videoFile.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
        StorePath storePath = storageClient.uploadFile(
                videoFile.getInputStream(), videoFile.getSize(), suffix, null);
        String videoUrl = fdfsWebServer.getWebServerUrl()+storePath.getFullPath();

        //3. 保存视频
        Video video = new Video();
        video.setCreated(System.currentTimeMillis());
        video.setUserId(UserHolder.getUserId());
        if (StringUtils.isEmpty(content)){
            // 设置默认值
            video.setText("左手右手一个慢动作~");
        } else {
            video.setText(content);
        }
        video.setPicUrl(picUrl);
        video.setVideoUrl(videoUrl);
        // 设置主键id
        video.setId(ObjectId.get());
        // 保存
        videoApi.save(video);

        // 发送消息
        videoMqService.videoMsg(video.getId().toString());

        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：视频用户关注
     */
    public ResponseEntity<Object> userFocus(Long followUserId) {
        //1. 创建并封装用户关注对象
        FollowUser followUser = new FollowUser();
        followUser.setCreated(System.currentTimeMillis());
        followUser.setUserId(UserHolder.getUserId());
        followUser.setFollowUserId(followUserId);
        //2. 调用api实现保存关注记录
        videoApi.userFocus(followUser);
        //3. 存储关注的状态到redis中（前端点亮图标，修改查询判断是否关注）
        String key = "followUser_" + UserHolder.getUserId() + "_" + followUser.getFollowUserId();
        redisTemplate.opsForValue().set(key,"1");
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：视频用户关注 - 取消
     */
    public ResponseEntity<Object> userUnFocus(Long followUserId) {
        //1. 获取登陆用户id
        Long userId = UserHolder.getUserId();
        //2. 调用Api实现取消用户关注
        videoApi.userUnFocus(userId,followUserId);
        //3. 删除redis中的关注状态
        String key = "followUser_" + UserHolder.getUserId() + "_" + followUserId;
        redisTemplate.delete(key);
        return ResponseEntity.ok(null);
    }
}
